#pragma once

/**
 * @file thread_utils.h
 * @brief 线程工具函数
 * @details 提供线程亲和性设置、线程创建和管理的工具函数
 */

#include <iostream>
#include <atomic>
#include <thread>
#include <unistd.h>

#include <sys/syscall.h>

namespace Common {
  /**
   * @brief 设置当前线程的CPU亲和性
   * 
   * @param core_id 目标CPU核心ID
   * @return 成功返回true，失败返回false
   */
  inline auto setThreadCore(int core_id) noexcept {
    cpu_set_t cpuset;

    CPU_ZERO(&cpuset);
    CPU_SET(core_id, &cpuset);

    return (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) == 0);
  }

  /**
   * @brief 创建并启动一个新线程，设置CPU亲和性并执行指定函数
   * 
   * @tparam T 函数类型
   * @tparam A 函数参数类型包
   * @param core_id 目标CPU核心ID，如果为负数则不设置亲和性
   * @param name 线程名称
   * @param func 线程执行的函数
   * @param args 传递给函数的参数
   * @return 创建的线程指针
   */
  template<typename T, typename... A>
  inline auto createAndStartThread(int core_id, const std::string &name, T &&func, A &&... args) noexcept {
    auto t = new std::thread([&]() {
      // 如果指定了核心ID（大于等于0），则设置线程亲和性
      if (core_id >= 0 && !setThreadCore(core_id)) {
        std::cerr << "Failed to set core affinity for " << name << " " << pthread_self() << " to " << core_id << std::endl;
        exit(EXIT_FAILURE);
      }
      std::cerr << "Set core affinity for " << name << " " << pthread_self() << " to " << core_id << std::endl;

      // 完美转发函数和参数，执行用户提供的函数
      std::forward<T>(func)((std::forward<A>(args))...);
    });

    // 引入时间字面量
    using namespace std::literals::chrono_literals;
    // 等待1秒，确保线程有足够时间启动并设置亲和性
    std::this_thread::sleep_for(1s);

    // 返回创建的线程指针，调用者负责管理线程对象的生命周期
    return t;
  }
}
